﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity;
using System.Windows.Controls.Primitives;

namespace RestaurantBooker.Controls
{

    /// <summary>
    /// Cjange SizedElement Size - only for Height was realized yet.
    /// </summary>
    public class ChangeSizeBehavior : Behavior<FrameworkElement>
    {
        /// <summary>
        /// The <see cref="IsActive" /> dependency property's name.
        /// </summary>
        public const string IsActivePropertyName = "IsActive";

        /// <summary>
        /// Gets or sets the value of the <see cref="IsActive" />
        /// property. This is a dependency property.
        /// True if the sizing function is active
        /// </summary>
        public bool IsActive
        {
            get
            {
                return (bool)GetValue(IsActiveProperty);
            }
            set
            {
                SetValue(IsActiveProperty, value);
            }
        }

        /// <summary>
        /// Identifies the <see cref="IsActive" /> dependency property.
        /// </summary>
        public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register(
            IsActivePropertyName,
            typeof(bool),
            typeof(ChangeSizeBehavior),
            new PropertyMetadata(true, new PropertyChangedCallback(IsActivePropertyChanged)));

        private static void IsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var obj = d as ChangeSizeBehavior;
            if (obj != null && obj.AssociatedObject != null)
            {
                if ((bool)e.NewValue)
                    obj.AssociatedObject.Cursor = Cursors.SizeNS;
                else
                    obj.AssociatedObject.Cursor = null;
            }
        }


        /// <summary>
        /// The <see cref="SizedElement" /> dependency property's name.
        /// </summary>
        public const string SizedElementPropertyName = "SizedElement";

        /// <summary>
        /// Gets or sets the value of the <see cref="SizedElement" />
        /// property. This is a dependency property.
        /// </summary>
        public FrameworkElement SizedElement
        {
            get
            {
                return (FrameworkElement)GetValue(SizedElementProperty);
            }
            set
            {
                SetValue(SizedElementProperty, value);
            }
        }

        /// <summary>
        /// Identifies the <see cref="SizedElement" /> dependency property.
        /// </summary>
        public static readonly DependencyProperty SizedElementProperty = DependencyProperty.Register(
            SizedElementPropertyName,
            typeof(FrameworkElement),
            typeof(ChangeSizeBehavior),
            new PropertyMetadata(null));

        private Point _initialResizePoint;
        private bool _isResizing;
        private DateTime _lastMouseDownTime = DateTime.MinValue;


        public ChangeSizeBehavior()
        {
        }

        protected override void OnAttached()
        {
            base.OnAttached();

            this.AssociatedObject.MouseLeftButtonDown += new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown);
            this.AssociatedObject.MouseLeftButtonUp += new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonUp);
            this.AssociatedObject.MouseMove += new MouseEventHandler(AssociatedObject_MouseMove);
        }

        public event DragDeltaEventHandler DragDeltaEventHandler;

        void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            
            if (IsActive)
            {
                _lastMouseDownTime = DateTime.Now;

                // Capture the mouse
                ((FrameworkElement)sender).CaptureMouse();
                this._initialResizePoint = e.GetPosition(App.Current.RootVisual as UIElement);
                // Set resizing to true
                _isResizing = true;
            }
        }


        void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
        {
            if (SizedElement != null && IsActive)
            {
                if (!_isResizing)
                {
                   
                }
                else
                {
                    // Point position = e.GetPosition(this.Parent as UIElement);
                    Point position = e.GetPosition(App.Current.RootVisual as UIElement);

                    var deltaX = _initialResizePoint.X - position.X;
                    var deltaY = _initialResizePoint.Y - position.Y;

                    _initialResizePoint = position;

                    if (DragDeltaEventHandler != null)
                    { 
                        DragDeltaEventHandler(this, new DragDeltaEventArgs(-deltaX, -deltaY));
                    }
                    else
                    {
                        //Change the size of the SizedElement
                        var h = (!double.IsNaN(SizedElement.Height) ? SizedElement.Height : SizedElement.ActualHeight) + deltaY;
                        if ((h <= SizedElement.MaxHeight) && (h >= SizedElement.MinHeight))
                            SizedElement.Height = h;
                        //SizedElement.Width = SizedElement.ActualWidth + deltaX;
                    }
                }
            }
        }

        void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {                   
            if (IsActive)
            {                
                ((FrameworkElement)sender).ReleaseMouseCapture();
                _isResizing = false;

                if ((DateTime.Now - _lastMouseDownTime).TotalMilliseconds < 400)
                {                    
                    _lastMouseDownTime = DateTime.MinValue;
                    // this is a simple click - need to send click event to a top element
                    return;
                }
                else
                    e.Handled = true;
            }
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            
            this.AssociatedObject.MouseLeftButtonDown -= new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown);
            this.AssociatedObject.MouseLeftButtonUp -= new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonUp);
            this.AssociatedObject.MouseMove -= new MouseEventHandler(AssociatedObject_MouseMove);
        }
    }
}
